//Source file: C:\\temp\\cn\\com\\microwin\\commis\\Configuration.java
package cn.com.hnisi.framework.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.util.regex.Matcher;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;

public class Configuration extends PropertyPlaceholderConfigurer {

	private static final Logger log = LogManager.getLogger(Configuration.class);

	private static Properties properties;
	private static Configuration config;
	private final static String ERR_MSG = "从配置文件中不能取得传入参数的返回值：";
	private static String ZK_HOST = "zkHost";
	private static String ZK_PORT = "zkPort";

	/**
	 * Use singleton pattern, only return one instance of Configuration.
	 * 
	 * @return Configuration
	 */
	public static Configuration getInstance() {
		return (Configuration) SpringUtil.getBean("configuration");
	}

	/**
	 * Retun a value for certain key.
	 * 
	 * @param key
	 *            a certain key define in properties file.
	 * @return value
	 */
	public String getValue(String key) {
		if (null == properties) {
			try {
				properties = mergeProperties();
			} catch (IOException e) {
				log.error(ERR_MSG + ":" + key);
				log.error(e);
			}
		}
		String value = properties.getProperty(key);
		if (value == null) {
			log.debug(ERR_MSG + ":" + key);
		}

		return value;
	}
	
	/**
	 * 获取属性值（属性值中带${}则相应的取值替换）
	 * add by duanbo 20140903
	 * 
	 * @param key 属性KEY
	 * @return 属性值
	 */
	public String getExpValue(String key)
	{
		String val = getValue(key);
		return processExpValue(val);
	}
	
	/**
	 * 处理表达式值
	 * add by duanbo 20140903
	 * 
	 * @param value 属性值（包含${}表达式）
	 * @return
	 */
	public String processExpValue(String value)
	{
		String regx = ".*\\$\\{.*\\}.*";
		String val = value;
		
		// 如果属性值不为空并且属性值中有${}表达式
		if(StringUtils.isNotBlank(val) && val.matches(regx))
		{
			// 处理属性值中的${}表达式
			for(String str = val; str.matches(regx);)
			{
				// key开始索引
				int startIndex = str.indexOf("${") + 2;
				// key结束索引
				int endIndex = str.indexOf("}");
				
				// 当前属性key
				String keyX = str.substring(startIndex, endIndex);
				// 当前属性表达式
				String exp = "\\$\\{" + keyX + "\\}";
				
				// 当前属性值
				String valX = getValue(keyX);
				String valY = valX;
				if(null != valY)
				{
					if(valY.matches(regx))
					{
						valY = processExpValue(valY);
					}
					
					if(null != valY)
					{
						if(valY.matches(regx) && StringUtils.equals(valX, valY))
						{
							log.warn(valY + " 中表达式处理失败！");
						}
						else
						{
							val = val.replaceAll(exp, Matcher.quoteReplacement(valY));
						}
					}
				}
				
				// 每处理掉一个就将替换掉一个，直到无
				str = str.replaceAll(exp, (null == valY || valY.matches(regx)) ? "" : Matcher.quoteReplacement(valY));
			}
		}
		
		return val;
	}
	
	public String getZkConfig(){
		return getValue(ZK_HOST, "") + ":" + getValue(ZK_PORT,"");
	}
	
	/**
	 * Retun a value for certain key.
	 * 
	 * @param key
	 *            a certain key define in properties file.
	 * @return value
	 */
	public String getValue(String key, String defaultValue) {
		if (!properties.containsKey(key))
			return defaultValue;
		return properties.getProperty(key).trim();
	}
	
	public void setValue(String key, String value){
		properties.setProperty(key, value);
	}

	public static void main(String[] args) {
		Configuration c = Configuration.getInstanceLocal();
		System.out.println(c.getValue("welcome.file"));
	}

	public static Configuration getInstanceLocal() {
		try {
			return getInstanceFromStream( new FileInputStream(new File("conf/sjjh.properties")));
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		return config;
	}
	
	public static Configuration getInstanceFromStream(InputStream cfgStream) {
		config = new Configuration();
		Properties prop = new Properties();
		try {
			prop.load(cfgStream);
		} catch (IOException e) {
			e.printStackTrace();
		}
		config.properties = prop;
		return config;
	}
}
